package com.azxc.rapid.auth.config;

import com.azxc.rapid.supervise.feign.ISuperviseClient;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import com.azxc.rapid.auth.constant.AuthConstant;
import com.azxc.rapid.auth.granter.RapidTokenGranter;
import com.azxc.rapid.auth.service.RapidClientDetailsServiceImpl;
import com.azxc.rapid.core.redis.cache.RapidRedis;
import com.azxc.rapid.core.social.props.SocialProperties;
import com.azxc.rapid.system.user.feign.IUserClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.TokenGranter;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;

/**
 * 认证服务器配置
 *
 *
 */
@Order
@Configuration
@EnableAuthorizationServer
public class RapidAuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

	@Autowired
	private  DataSource dataSource;
	@Autowired
	private  AuthenticationManager authenticationManager;
	@Autowired
	private  UserDetailsService userDetailsService;
	@Autowired
	private  TokenStore tokenStore;
	@Autowired
	private  TokenEnhancer jwtTokenEnhancer;
	@Autowired
	private  JwtAccessTokenConverter jwtAccessTokenConverter;
	@Autowired
	private  RapidRedis rapidRedis;
	@Autowired
	private  IUserClient userClient;
	@Autowired
	private  SocialProperties socialProperties;
	@Autowired
	private  ISuperviseClient superviseClient;

	// 通过这里注入门户相关配置
	@Value("${portal.clientId:}")
	public   String clientId;
	@Value("${portal.clientSecret:}")
	public  String clientSecret;
	@Value("${portal.portalUrl:}")
	public  String portalUrl;
	@Value("${portal.redirectUri:}")
	public  String redirectUri;

	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
		//获取自定义tokenGranter
		TokenGranter tokenGranter = RapidTokenGranter.getTokenGranter(authenticationManager, endpoints, rapidRedis, userClient, socialProperties,superviseClient,
			clientId,clientSecret,portalUrl,redirectUri);
		//配置端点
		endpoints.tokenStore(tokenStore)
			.authenticationManager(authenticationManager) //.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
			.userDetailsService(userDetailsService)
			.tokenGranter(tokenGranter);

		//扩展token返回结果
		if (jwtAccessTokenConverter != null && jwtTokenEnhancer != null) {
			TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
			List<TokenEnhancer> enhancerList = new ArrayList<>();
			enhancerList.add(jwtTokenEnhancer);
			enhancerList.add(jwtAccessTokenConverter);
			tokenEnhancerChain.setTokenEnhancers(enhancerList);
			//jwt增强
			endpoints.tokenEnhancer(tokenEnhancerChain).accessTokenConverter(jwtAccessTokenConverter);
		}
	}

	/**
	 * 配置客户端信息
	 */
	@Override
	@SneakyThrows
	public void configure(ClientDetailsServiceConfigurer clients) {
		RapidClientDetailsServiceImpl clientDetailsService = new RapidClientDetailsServiceImpl(dataSource);
		clientDetailsService.setSelectClientDetailsSql(AuthConstant.DEFAULT_SELECT_STATEMENT);
		clientDetailsService.setFindClientDetailsSql(AuthConstant.DEFAULT_FIND_STATEMENT);
		clients.withClientDetails(clientDetailsService);
	}

	@Override
	public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
		oauthServer
			.allowFormAuthenticationForClients()
			.tokenKeyAccess("permitAll()")
			.checkTokenAccess("isAuthenticated()");
	}

}
